<!-- Monaco Editor 组件 -->
<template>
  <div ref="editorContainer" class="monaco-editor-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as monaco from 'monaco-editor'

const props = defineProps<{
  modelValue: string
  language?: string
  theme?: string
  readOnly?: boolean
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()

const editorContainer = ref<HTMLElement>()
let editor: monaco.editor.IStandaloneCodeEditor | null = null

// 添加 Nginx 语法高亮定义
const registerNginxLanguage = () => {
  monaco.languages.register({ id: 'nginx' })
  monaco.languages.setMonarchTokensProvider('nginx', {
    keywords: [
      'daemon', 'env', 'debug_points', 'error_log', 'include', 'lock_file', 'master_process',
      'pid', 'ssl_engine', 'timer_resolution', 'user', 'worker_cpu_affinity',
      'worker_priority', 'worker_processes', 'worker_rlimit_core', 'worker_rlimit_nofile',
      'worker_rlimit_sigpending', 'working_directory', 'accept_mutex', 'accept_mutex_delay',
      'debug_connection', 'devpoll_changes', 'devpoll_events', 'kqueue_changes',
      'kqueue_events', 'epoll_events', 'multi_accept', 'rtsig_overflow_events',
      'rtsig_overflow_test', 'rtsig_overflow_threshold', 'rtsig_signo', 'use',
      'worker_connections', 'aio', 'alias', 'chunked_transfer_encoding', 'client_body_in_file_only',
      'client_body_in_single_buffer', 'client_body_buffer_size', 'client_body_temp_path',
      'client_body_timeout', 'client_header_buffer_size', 'client_header_timeout',
      'client_max_body_size', 'default_type', 'directio', 'error_page', 'if_modified_since',
      'internal', 'keepalive_timeout', 'keepalive_requests', 'large_client_header_buffers',
      'limit_except', 'limit_rate', 'limit_rate_after', 'listen', 'location',
      'log_not_found', 'log_subrequest', 'msie_padding', 'msie_refresh',
      'open_file_cache', 'open_file_cache_errors', 'open_file_cache_min_uses',
      'open_file_cache_valid', 'optimize_server_names', 'port_in_redirect',
      'proxy_buffer_size', 'proxy_buffering', 'proxy_buffers', 'proxy_busy_buffers_size',
      'proxy_cache', 'proxy_cache_path', 'proxy_cache_methods', 'proxy_cache_min_uses',
      'proxy_cache_valid', 'proxy_cache_use_stale', 'proxy_cache_key',
      'proxy_connect_timeout', 'proxy_headers_hash_bucket_size', 'proxy_headers_hash_max_size',
      'proxy_hide_header', 'proxy_ignore_client_abort', 'proxy_ignore_headers',
      'proxy_intercept_errors', 'proxy_max_temp_file_size', 'proxy_method',
      'proxy_next_upstream', 'proxy_pass_header', 'proxy_pass_request_body',
      'proxy_pass_request_headers', 'proxy_pass', 'proxy_read_timeout',
      'proxy_redirect_errors', 'proxy_redirect', 'proxy_send_lowat', 'proxy_send_timeout',
      'proxy_set_body', 'proxy_set_header', 'proxy_temp_file_write_size', 'proxy_temp_path',
      'proxy_upstream_fail_timeout', 'proxy_upstream_max_fails', 'recursive_error_pages',
      'resolver', 'resolver_timeout', 'root', 'satisfy_any', 'send_timeout',
      'sendfile', 'server_name', 'server_names_hash_bucket_size', 'server_names_hash_max_size',
      'server_tokens', 'server', 'tcp_nodelay', 'tcp_nopush', 'try_files',
      'types', 'upstream', 'userid', 'userid_domain', 'userid_expires', 'userid_name',
      'userid_p3p', 'userid_path', 'userid_service', 'valid_referers', 'set',
      'access_log', 'add_after_body', 'add_before_body', 'add_header', 'addition_types',
      'auth_basic', 'auth_basic_user_file', 'autoindex', 'autoindex_exact_size',
      'autoindex_localtime', 'break', 'charset', 'charset_map', 'charset_types',
      'create_full_put_path', 'dav_access', 'dav_methods', 'deny', 'echo',
      'echo_after_body', 'echo_before_body', 'echo_blocking_sleep', 'echo_duplicate',
      'echo_end', 'echo_exec', 'echo_flush', 'echo_foreach_split', 'echo_location',
      'echo_location_async', 'echo_read_request_body', 'echo_request_body',
      'echo_reset_timer', 'echo_sleep', 'echo_subrequest', 'echo_subrequest_async',
      'empty_gif', 'fastcgi_bind', 'fastcgi_buffer_size', 'fastcgi_buffers',
      'fastcgi_busy_buffers_size', 'fastcgi_cache', 'fastcgi_cache_key',
      'fastcgi_cache_methods', 'fastcgi_cache_min_uses', 'fastcgi_cache_path',
      'fastcgi_cache_use_stale', 'fastcgi_cache_valid', 'fastcgi_catch_stderr',
      'fastcgi_connect_timeout', 'fastcgi_hide_header', 'fastcgi_ignore_client_abort',
      'fastcgi_ignore_headers', 'fastcgi_index', 'fastcgi_intercept_errors',
      'fastcgi_max_temp_file_size', 'fastcgi_next_upstream', 'fastcgi_param',
      'fastcgi_pass_header', 'fastcgi_pass_request_body', 'fastcgi_pass_request_headers',
      'fastcgi_pass', 'fastcgi_read_timeout', 'fastcgi_send_lowat', 'fastcgi_send_timeout',
      'fastcgi_split_path_info', 'fastcgi_store_access', 'fastcgi_store',
      'fastcgi_temp_file_write_size', 'fastcgi_temp_path', 'flv', 'geo',
      'geoip_city', 'geoip_country', 'gzip', 'gzip_buffers', 'gzip_comp_level',
      'gzip_disable', 'gzip_http_version', 'gzip_min_length', 'gzip_proxied',
      'gzip_types', 'gzip_vary', 'http', 'if', 'ignore_invalid_headers',
      'image_filter', 'image_filter_buffer', 'image_filter_jpeg_quality',
      'image_filter_transparency', 'imap_capabilities', 'index', 'limit_conn',
      'limit_conn_log_level', 'limit_rate', 'limit_req', 'limit_req_log_level',
      'limit_req_zone', 'limit_zone', 'lingering_time', 'lingering_timeout',
      'map_hash_bucket_size', 'map_hash_max_size', 'map', 'memcached_bind',
      'memcached_buffer_size', 'memcached_connect_timeout', 'memcached_next_upstream',
      'memcached_pass', 'memcached_read_timeout', 'memcached_send_timeout',
      'merge_slashes', 'min_delete_depth', 'modern_browser', 'modern_browser_value',
      'more_clear_headers', 'more_clear_input_headers', 'more_set_headers',
      'more_set_input_headers', 'mp4', 'open_log_file_cache', 'override_charset',
      'perl_modules', 'perl_require', 'perl_set', 'perl', 'pop3_auth',
      'pop3_capabilities', 'port_in_redirect', 'postpone_output', 'protocol',
      'proxy_cache_bypass', 'proxy_cache_lock', 'proxy_cache_lock_timeout',
      'proxy_cache_methods', 'proxy_cache_min_uses', 'proxy_cache_path',
      'proxy_cache_use_stale', 'proxy_cache_valid', 'proxy_cookie_domain',
      'proxy_cookie_path', 'proxy_headers_hash_bucket_size', 'proxy_headers_hash_max_size',
      'proxy_hide_header', 'proxy_http_version', 'proxy_ignore_client_abort',
      'proxy_ignore_headers', 'proxy_intercept_errors', 'proxy_max_temp_file_size',
      'proxy_method', 'proxy_next_upstream', 'proxy_no_cache', 'proxy_pass_error_message',
      'proxy_pass_header', 'proxy_pass_request_body', 'proxy_pass_request_headers',
      'proxy_pass', 'proxy_read_timeout', 'proxy_redirect', 'proxy_send_lowat',
      'proxy_send_timeout', 'proxy_set_body', 'proxy_set_header', 'proxy_ssl_session_reuse',
      'proxy_store_access', 'proxy_store', 'proxy_temp_file_write_size',
      'proxy_temp_path', 'random_index', 'read_ahead', 'real_ip_header',
      'real_ip_recursive', 'referer_hash_bucket_size', 'referer_hash_max_size',
      'request_pool_size', 'reset_timedout_connection', 'resolver_timeout',
      'return', 'rewrite_log', 'rewrite', 'satisfy_any', 'secure_link_secret',
      'secure_link_md5', 'secure_link', 'send_lowat', 'send_timeout',
      'sendfile_max_chunk', 'server_name_in_redirect', 'server_name', 'server_names_hash_bucket_size',
      'server_names_hash_max_size', 'server_tokens', 'server', 'set_real_ip_from',
      'smtp_auth', 'smtp_capabilities', 'smtp_client', 'smtp_greeting_delay',
      'source_charset', 'ssi', 'ssi_ignore_recycled_buffers', 'ssi_min_file_chunk',
      'ssi_silent_errors', 'ssi_types', 'ssi_value_length', 'ssl',
      'ssl_certificate_key', 'ssl_client_certificate', 'ssl_certificate',
      'ssl_ciphers', 'ssl_crl', 'ssl_dhparam', 'ssl_engine',
      'ssl_prefer_server_ciphers', 'ssl_protocols', 'ssl_session_cache',
      'ssl_session_timeout', 'ssl_verify_client', 'ssl_verify_depth',
      'starttls', 'stub_status', 'sub_filter_once', 'sub_filter_types',
      'sub_filter', 'tcp_nodelay', 'tcp_nopush', 'timer_resolution',
      'try_files', 'types_hash_bucket_size', 'types_hash_max_size',
      'underscores_in_headers', 'uninitialized_variable_warn', 'upstream_ip_hash',
      'upstream', 'use', 'user', 'userid_domain', 'userid_expires',
      'userid_mark', 'userid_name', 'userid_p3p', 'userid_path',
      'userid_service', 'valid_referers', 'variables_hash_bucket_size',
      'variables_hash_max_size', 'worker_connections', 'worker_cpu_affinity',
      'worker_priority', 'worker_processes', 'worker_rlimit_core',
      'worker_rlimit_nofile', 'worker_rlimit_sigpending', 'working_directory',
      'xml_entities', 'xslt_stylesheet', 'xslt_types'
    ],

    tokenizer: {
      root: [
        // 注释
        [/#.*$/, 'comment'],

        // 字符串 - 修改这部分规则
        [/'[^']*'/, 'string'],  // 单引号字符串
        [/"[^"]*"/, 'string'],  // 双引号字符串
        [/`[^`]*`/, 'string'],  // 反引号字符串

        // 数字
        [/\d*\.\d+([eE][-+]?\d+)?/, 'number.float'],
        [/\d+/, 'number'],

        // 变量
        [/\$[a-zA-Z_]\w*/, 'variable'],
        [/\$\{[^}]+\}/, 'variable'],  // 添加对 ${var} 格式变量的支持

        // Nginx 特殊变量
        [/\$(?:request|remote_addr|remote_user|time_local|status|body_bytes_sent|http_referer|http_user_agent|http_x_forwarded_for|http_host)\b/, 'variable.predefined'],

        // 关键字
        [/[a-zA-Z_]\w*/, {
          cases: {
            '@keywords': 'keyword',
            '@default': 'identifier'
          }
        }],

        // 分隔符和运算符
        [/[;,.]/, 'delimiter'],
        [/[(){}[\]]/, '@brackets'],
        [/[<>](?!@symbols)/, '@brackets'],
        [/@symbols/, {
          cases: {
            '@operators': 'operator',
            '@default': ''
          }
        }]
      ],

      // 移除 string 状态，因为我们现在在 root 中直接处理字符串
    },

    symbols: /[=><!~?:&|+\-*/^%]+/,
    escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
    operators: [
      '=', '>', '<', '!', '~', '?', ':',
      '&', '|', '+', '-', '*', '/', '^', '%'
    ]
  })
}

// 初始化编辑器
const initMonaco = async () => {
  if (!editorContainer.value) return

  registerNginxLanguage()

  editor = monaco.editor.create(editorContainer.value, {
    value: props.modelValue,
    language: props.language || 'nginx',
    theme: props.theme || 'vs-dark',
    automaticLayout: true,
    minimap: {
      enabled: true
    },
    scrollBeyondLastLine: false,
    fontSize: 14,
    lineNumbers: 'on',
    readOnly: props.readOnly,
    roundedSelection: false,
    scrollbar: {
      useShadows: false,
      verticalScrollbarSize: 10,
      horizontalScrollbarSize: 10
    },
    padding: {
      top: 20
    }
  })

  // 监听内容变化
  editor.onDidChangeModelContent(() => {
    const value = editor?.getValue() || ''
    emit('update:modelValue', value)
  })
}

// 监听 props 变化
watch(() => props.modelValue, (newValue) => {
  if (editor && newValue !== editor.getValue()) {
    editor.setValue(newValue)
  }
})

watch(() => props.readOnly, (newValue) => {
  if (editor) {
    editor.updateOptions({ readOnly: newValue })
  }
})

// 组件挂载时初始化
onMounted(() => {
  initMonaco()
})

// 组件销毁时清理
onBeforeUnmount(() => {
  if (editor) {
    editor.dispose()
  }
})
</script>

<style scoped>
.monaco-editor-container {
  width: 100%;
  height: 100%;
  min-height: 300px;
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
}
</style> 